package cn.zzdt4j.config.service.biz.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.zzdt4j.common.extension.enums.DelEnum;
import cn.zzdt4j.common.toolkit.BeanUtil;
import cn.zzdt4j.config.mapper.TenantInfoMapper;
import cn.zzdt4j.config.model.TenantInfo;
import cn.zzdt4j.config.model.biz.item.ItemQueryReqDTO;
import cn.zzdt4j.config.model.biz.item.ItemRespDTO;
import cn.zzdt4j.config.model.biz.tenant.TenantQueryReqDTO;
import cn.zzdt4j.config.model.biz.tenant.TenantRespDTO;
import cn.zzdt4j.config.model.biz.tenant.TenantSaveReqDTO;
import cn.zzdt4j.config.model.biz.tenant.TenantUpdateReqDTO;
import cn.zzdt4j.config.service.biz.ItemService;
import cn.zzdt4j.config.service.biz.TenantService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.List;
import java.util.stream.Collectors;

/**
 * The type Tenant service.
 *
 * @author by <a href="mailto:ligang941012@gmail.com">gang.Li</a>
 * @since 2023 /11/6 12:45
 */
@Service
@AllArgsConstructor
public class TenantServiceImpl implements TenantService {

    private final TenantInfoMapper tenantInfoMapper;

    private final ItemService itemService;

    @Override
    public void deleteTenantById(String tenantId) {
        ItemQueryReqDTO reqDTO = new ItemQueryReqDTO();
        reqDTO.setTenantId(tenantId);
        List<ItemRespDTO> itemRespDTOList = itemService.queryItem(reqDTO);
        if (CollectionUtil.isNotEmpty(itemRespDTOList)) {
            throw new RuntimeException("租户包含项目引用，删除失败。");
        }
        final int updateResult = tenantInfoMapper.update(new TenantInfo(),
                Wrappers.lambdaUpdate(TenantInfo.class)
                        .eq(TenantInfo::getTenantId, tenantId)
                        .eq(TenantInfo::getDelFlag, DelEnum.DELETE.getIntCode()));
        if (!SqlHelper.retBool(updateResult)) {
            throw new RuntimeException("TenantInfo Delete Error. ");
        }
    }

    @Override
    public void saveTenant(TenantSaveReqDTO reqDTO) {
        final LambdaQueryWrapper<TenantInfo> queryWrapper = Wrappers.lambdaQuery(TenantInfo.class)
                .eq(TenantInfo::getTenantId, reqDTO.getTenantId());
        // Currently it is a single application, and it supports switching distributed locks during cluster deployment in the future.
        synchronized (TenantService.class) {
            final TenantInfo existTenantInfo = tenantInfoMapper.selectOne(queryWrapper);
            Assert.isNull(existTenantInfo, "租户配置已存在。");
            final TenantInfo tenantInfo = BeanUtil.convert(reqDTO, TenantInfo.class);
            final int insertResult = tenantInfoMapper.insert(tenantInfo);
            if (!SqlHelper.retBool(insertResult)) {
                throw new RuntimeException("TenantInfo Save Error. ");
            }
        }
    }

    @Override
    public void updateTenant(TenantUpdateReqDTO reqDTO) {
        final TenantInfo tenantInfo = BeanUtil.convert(reqDTO, TenantInfo.class);
        final int updateResult = tenantInfoMapper.update(tenantInfo, Wrappers.lambdaUpdate(TenantInfo.class)
                .eq(TenantInfo::getTenantId, reqDTO.getTenantId()));
        if (!SqlHelper.retBool(updateResult)) {
            throw new RuntimeException("TenantInfo Update Error. ");
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public IPage<TenantRespDTO> queryTenantPage(TenantQueryReqDTO reqDTO) {
        final LambdaQueryWrapper<TenantInfo> wrapper = Wrappers.lambdaQuery(TenantInfo.class)
                .eq(StrUtil.isNotEmpty(reqDTO.getTenantId()), TenantInfo::getTenantId, reqDTO.getTenantId())
                .eq(StrUtil.isNotEmpty(reqDTO.getTenantName()), TenantInfo::getTenantName, reqDTO.getTenantName())
                .eq(StrUtil.isNotEmpty(reqDTO.getOwner()), TenantInfo::getOwner, reqDTO.getOwner())
                .orderByDesc(reqDTO.getDesc() != null, TenantInfo::getGmtCreate);
        final Page resultPage = tenantInfoMapper.selectPage(reqDTO, wrapper);
        return resultPage.convert(each -> BeanUtil.convert(each, TenantRespDTO.class));
    }

    @Override
    public List<String> listAllTenant() {
        final List<TenantInfo> tenantInfos = tenantInfoMapper.selectList(Wrappers.emptyWrapper());
        return tenantInfos.stream().map(TenantInfo::getTenantId).collect(Collectors.toList());
    }
}
